"""
邮箱主界面
1、发邮件
2、收邮件
3、垃圾邮件识别
...后续功能待添加...
"""
import sys
import time
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *

from client.client_pop import *
from client.client_smtp import *
from client.client_emailbox import *
from client.win_index import Ui_MainWindow

class Call_index(QMainWindow, Ui_MainWindow):
    def __init__(self, parent =None):
        super(Call_index, self).__init__(parent)
        self.setupUi(self)
        self.setupWin()
        """
        定义参数
        """
        self.__userSmtp = ClientSmtp()
        self.__userPop = ClientPop()
        self.emailBox = ClientEmailBox()
        self.emailInfoList = []
        self.gubbage_email_list = []
        self.read_email_win = QMainWindow()

        """
        线程初始化及信号槽绑定
        1、线程结束发送信号至槽函数display_is_send同时关闭计时器
        2、计时器超时关闭计时器，杀死线程，发送信号至槽函数display_is_send
        """
        self.clock_send_email = QTimer()
        self.thread_send_email = sentEmail()
        self.thread_send_email.trigger[bool, list].connect(self.display_is_send)
        self.thread_send_email.trigger.connect(self.clock_send_email.stop)
        self.clock_send_email.timeout.connect(self.clock_send_email.stop)
        self.clock_send_email.timeout.connect(self.thread_send_email.terminate)
        self.clock_send_email.timeout.connect(lambda: self.display_is_send(False, ['smtp连接超时，验证失败']))

        """
        线程初始化及信号槽绑定
        1、线程结束发送信号至槽函数set_gubbage_email
        """
        self.thread_get_gubbage_email = getGubbageEmail()
        self.thread_get_gubbage_email.trigger[dict,list].connect(self.set_gubbage_email)

        """
        线程初始化及信号槽绑定
        1、线程结束发送信号至槽函数setEmail
        """
        self.getEmailThread = getEmail()
        self.getEmailThread.trigger[list, list, ClientEmailBox].connect(self.setEmail)
        """
        ‘发送邮件’按钮点击信号绑定槽函数sendEmail
        ‘清除’按钮点击信号绑定槽函数clearBody
        ‘表格单元格’右击信号绑定槽函数generateMenu
        ‘表格单元格’双击信号绑定槽函数read_email
        """
        self.pushButtonSend.clicked.connect(self.sendEmail)
        self.pushButtonClear.clicked.connect(self.clearBody)
        self.tableEmail.customContextMenuRequested.connect(self.generateMenu)
        self.tableEmail.cellDoubleClicked.connect(self.read_email)
        self.gubbage_email.cellDoubleClicked.connect(self.read_email)

    """
    初始化窗口
    1、tableEmail表格格式设置
    2、gubbage_email表格格式设置
    3、移除垃圾邮件的窗口
    4、‘divede’功能键绑定槽函数divide
    """
    def setupWin(self):
        self.tableEmail.setShowGrid(False)
        self.tableEmail.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.tableEmail.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.tableEmail.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.tableEmail.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tabWidget.removeTab(2)
        self.action_divede.triggered.connect(self.divide)

        self.gubbage_email.setShowGrid(False)
        self.gubbage_email.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.gubbage_email.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.gubbage_email.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.gubbage_email.setContextMenuPolicy(Qt.CustomContextMenu)

    """
    性质：槽函数
    功能：右击显示菜单栏
        1、删除邮件
        ...后续功能有待开发...
    """
    def generateMenu(self,pos):
        row_index = self.tableEmail.selectedIndexes()
        current_row = row_index[0].row()
        if current_row < len(self.emailInfoList):
            menu = QMenu()
            item = menu.addAction(u"删除")
            action = menu.exec_(self.tableEmail.mapToGlobal(pos))
            if action == item:
                try:
                    print("正在执行删除")
                    delete_flag,ms = self.__userPop.delete_email(current_row)
                except Exception as err:
                    print(err)
                if delete_flag:
                    print(self.emailInfoList[current_row]['Subject'])
                    print("%s %s %s"%('主题为："',self.emailInfoList[current_row]['Subject'],'"删除成功'))
                    self.tableEmail.removeRow(current_row)

    """
    初始化__userSmtp
    """
    def set_smtp(self, ClientSmtp):
        self.__userSmtp = ClientSmtp

    """
    初始化__userPop
    """
    def set_pop(self, ClientPop):
        self.__userPop = ClientPop

    """
    性质：槽函数
    功能：弹出'伪浏览器'阅读邮件
    """
    def read_email(self,row):
        html = self.emailInfoList[row]['content']
        self.browser = QWebEngineView()
        self.browser.setHtml(html)
        self.read_email_win.setCentralWidget(self.browser)
        self.read_email_win.show()

    """
    性质：槽函数
    作用：唤醒区分垃圾邮件的线程
    """
    def divide(self):
        self.tabWidget.addTab(self.guEmWin,"垃圾邮件")
        self.tableEmail.setHorizontalHeaderLabels(['发送者', '主题', '正文', '', "", '日期'])
        self.thread_get_gubbage_email.setAttribute(self.emailBox)
        self.thread_get_gubbage_email.start()

    """
    作用：往gubbage_email表格里面填邮件
    """
    def set_gubbage_email(self,gubbage_email_flag,errlist):
        for key in gubbage_email_flag:
            if gubbage_email_flag[key] == "spam":
                self.gubbage_email_list.append(key)
        self.gubbage_email.setColumnCount(6)
        self.gubbage_email.setRowCount(len(self.gubbage_email_list))
        for index in range(len(self.gubbage_email_list)):
            email = self.emailInfoList[self.gubbage_email_list[index]]
            try:
                self.gubbage_email.setSpan(index, 2, 1, 3)
                self.gubbage_email.setItem(index, 0, QTableWidgetItem(email['Sender']))
                self.gubbage_email.setItem(index, 1, QTableWidgetItem(email['Subject']))
                self.gubbage_email.setItem(index, 2, QTableWidgetItem(email['content']))
                self.gubbage_email.setItem(index, 5, QTableWidgetItem(email['Date']))
            except Exception as err:
                errlist.append(err)

    """
    性质：槽函数
    作用：判断邮件是否发送成功
    """
    def display_is_send(self,flag,errlist):
        if flag == True:
            print("邮件发送成功...")
            QMessageBox.information(self,"","邮件发送成功...",QMessageBox.Yes)
        else:
            for index in range(len(errlist)):
                print("%s\t%s" % ("邮件发送失败...",errlist[index]))
                QMessageBox.information(self, "", "邮件发送失败...", QMessageBox.Yes)

    """
    性质：槽函数
    作用：唤醒发送邮件的线程
    """
    def sendEmail(self):
        #获取表单属性
        fromAddress = self.__userSmtp.get_username()
        toAddress = self.lineEditAddress.text()
        emailTheme = self.lineEditTheme.text()
        emailBody = self.textEditBody.toPlainText()
        #构造邮件
        msg = self.emailBox.build_email(fromAddress, toAddress, emailTheme, emailBody)
        self.thread_send_email.setAttribute(msg,self.__userSmtp,fromAddress,toAddress)
        self.clock_send_email.start(2000)
        self.thread_send_email.start()

    """
    性质：槽函数
    作用：清除邮件正文内容
    """
    def clearBody(self):
        self.textEditBody.clear()

    """
    作用：唤醒接受邮件的线程
    """
    def getEmail(self):
        flag,msg = self.__userPop.is_connecting()
        if(flag==False):
            print("POP连接断开，重连中...")
            flag1, msg1 = self.__userPop.reconnect()
            if(flag1):
                print("%s %s" % ("重连成功", msg1))
            else:
                print("%s %s"%("重连失败",msg1))
        else:
            self.getEmailThread.setAttribute(self.__userPop)
            self.getEmailThread.start()

    """
    性质：槽函数
    作用：往tableEmail表格里面填邮件
    """
    def setEmail(self,email_lisy,errlist,clientbox):
        self.emailBox = clientbox
        self.emailInfoList = email_lisy
        self.tableEmail.setColumnCount(6)
        self.tableEmail.setRowCount(len(self.emailInfoList))
        self.tableEmail.setHorizontalHeaderLabels(['发送者','主题','正文','',"",'日期'])
        for index in range(len(self.emailInfoList)):
            try:
                self.tableEmail.setSpan(index,2,1,3)
                self.tableEmail.setItem(index, 0, QTableWidgetItem(self.emailInfoList[index]['Sender']))
                self.tableEmail.setItem(index, 1,QTableWidgetItem(self.emailInfoList[index]['Subject']))
                self.tableEmail.setItem(index, 2, QTableWidgetItem(self.emailInfoList[index]['text']))
                self.tableEmail.setItem(index, 5, QTableWidgetItem(self.emailInfoList[index]['Date']))
            except Exception as err:
                errlist.append(err)
        if len(errlist)>0:
            print("------------- 邮件接受错误 -------------")
            for index in range(len(errlist)):
                print('-'+str(errlist[index])+'-')
            print("---------------------------------------")

"""
性质：线程类
作用：接受邮件
"""
class getEmail(QThread):
    trigger = pyqtSignal(list,list,ClientEmailBox)
    clientpop = None
    clientmailbox = ClientEmailBox("127.0.0.1",20123)
    email_list = []

    def __init__(self):
        super(getEmail, self).__init__()
    def setAttribute(self,ClientPop):
        self.clientpop = ClientPop
    def run(self):
        errlist = []
        list = self.clientpop.get_emails()
        parser_email_flag, msg = self.clientmailbox.parser_email(list)
        if not parser_email_flag:
            errlist.append(msg)
        header,content,text= self.clientmailbox.get_emails()
        for index in range(len(header)):
            emailInfo = {
                'Sender': "None",
                'Subject': 'None',
                'content': 'None',
                'text':'None',
                'Date': 'None'
            }
            try:
                if 'Sender' in header[index].keys():
                    emailInfo['Sender'] = header[index]['Sender']
                elif 'from' in header[index].keys():
                    emailInfo['Sender'] = header[index]['from']
                if 'Subject' in header[index].keys():
                    emailInfo['Subject'] = header[index]['Subject']
                if 'Date' in header[index].keys():
                    emailInfo['Date'] = header[index]['Date']

            except Exception as err:
                errlist.append({index:err})
            emailInfo['content'] = content[index]
            try:
                emailInfo['text'] = text[index]
            except Exception as err:
                emailInfo['text'] = 'None'
            self.email_list.append(emailInfo)
        self.trigger.emit(self.email_list,errlist,self.clientmailbox)

"""
性质：线程类
作用：发送邮件
"""
class sentEmail(QThread):
    msg = None
    smtp = None
    fromAddress = None
    toAddress = None
    trigger = pyqtSignal(bool,list)
    def __init__(self):
        super(sentEmail, self).__init__()
    def setAttribute(self,msg,smtp,fromAddress,toAddress):
        self.msg = msg
        self.smtp = smtp
        self.fromAddress = fromAddress
        self.toAddress = toAddress
    def run(self):
        flag,msg = self.smtp.reconnect()
        username = self.smtp.get_username()
        password = self.smtp.get_password()
        errlist = []
        if flag == False:
            print(msg)
        else:
            try:

                self.smtp.login(username, password)
                flag, msg = self.smtp.send_mail(self.fromAddress, self.toAddress, self.msg)
                if flag == False:
                    errlist.append(msg)
            except Exception as err:
                errlist.append(err)
        self.trigger.emit(flag,errlist)

"""
性质：线程类
作用：获取垃圾邮件下标
"""
class getGubbageEmail(QThread):
    trigger = pyqtSignal(dict,list)
    emailBox = None
    def __init__(self):
        super(getGubbageEmail, self).__init__()
    def setAttribute(self,emailBox):
        self.emailBox = emailBox
    def run(self):
        errlist = []
        gubbage_email_flag = {}
        self.emailBox.set_email_class()
        time.sleep(2)
        try:
            gubbage_email_flag = self.emailBox.get_email_class()
        except Exception as err:
            errlist.append(err)
        self.trigger.emit(gubbage_email_flag,errlist)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    myWin = Call_index()
    myWin.show()
    sys.exit(app.exec_())






